home *** CD-ROM | disk | FTP | other *** search
/ Introduction to 3D Game …ogramming with DirectX 12 / Introduction-to-3D-Game-Programming-with-DirectX-12.ISO / Code.Textures / Chapter 13 The Compute Shader / SobelFilter / GpuWaves.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  2016-03-02  |  9.8 KB  |  307 lines

  1. //***************************************************************************************
  2. // GpuWaves.cpp by Frank Luna (C) 2011 All Rights Reserved.
  3. //***************************************************************************************
  4.  
  5. #include "GpuWaves.h"
  6. #include "Effects.h"
  7. #include <algorithm>
  8. #include <vector>
  9. #include <cassert>
  10.  
  11. GpuWaves::GpuWaves(ID3D12Device* device, ID3D12GraphicsCommandList* cmdList, 
  12.                    int m, int n, float dx, float dt, float speed, float damping)
  13. {
  14.     md3dDevice = device;
  15.  
  16.     mNumRows = m;
  17.     mNumCols = n;
  18.  
  19.     assert((m*n) % 256 == 0);
  20.  
  21.     mVertexCount = m*n;
  22.     mTriangleCount = (m - 1)*(n - 1) * 2;
  23.  
  24.     mTimeStep = dt;
  25.     mSpatialStep = dx;
  26.  
  27.     float d = damping*dt + 2.0f;
  28.     float e = (speed*speed)*(dt*dt) / (dx*dx);
  29.     mK[0] = (damping*dt - 2.0f) / d;
  30.     mK[1] = (4.0f - 8.0f*e) / d;
  31.     mK[2] = (2.0f*e) / d;
  32.  
  33.     BuildResources(cmdList);
  34. }
  35.  
  36. UINT GpuWaves::RowCount()const
  37. {
  38.     return mNumRows;
  39. }
  40.  
  41. UINT GpuWaves::ColumnCount()const
  42. {
  43.     return mNumCols;
  44. }
  45.  
  46. UINT GpuWaves::VertexCount()const
  47. {
  48.     return mVertexCount;
  49. }
  50.  
  51. UINT GpuWaves::TriangleCount()const
  52. {
  53.     return mTriangleCount;
  54. }
  55.  
  56. float GpuWaves::Width()const
  57. {
  58.     return mNumCols*mSpatialStep;
  59. }
  60.  
  61. float GpuWaves::Depth()const
  62. {
  63.     return mNumRows*mSpatialStep;
  64. }
  65.  
  66. float GpuWaves::SpatialStep()const
  67. {
  68.     return mSpatialStep;
  69. }
  70.  
  71. CD3DX12_GPU_DESCRIPTOR_HANDLE GpuWaves::DisplacementMap()const
  72. {
  73.     return mCurrSolSrv;
  74. }
  75.  
  76. UINT GpuWaves::DescriptorCount()const
  77. {
  78.     // Number of descriptors in heap to reserve for GpuWaves.
  79.     return 6;
  80. }
  81.  
  82. void GpuWaves::BuildResources(ID3D12GraphicsCommandList* cmdList)
  83. {
  84.     // All the textures for the wave simulation will be bound as a shader resource and
  85.     // unordered access view at some point since we ping-pong the buffers.
  86.  
  87.     D3D12_RESOURCE_DESC texDesc;
  88.     ZeroMemory(&texDesc, sizeof(D3D12_RESOURCE_DESC));
  89.     texDesc.Dimension = D3D12_RESOURCE_DIMENSION_TEXTURE2D;
  90.     texDesc.Alignment = 0;
  91.     texDesc.Width = mNumCols;
  92.     texDesc.Height = mNumRows;
  93.     texDesc.DepthOrArraySize = 1;
  94.     texDesc.MipLevels = 1;
  95.     texDesc.Format = DXGI_FORMAT_R32_FLOAT;
  96.     texDesc.SampleDesc.Count = 1;
  97.     texDesc.SampleDesc.Quality = 0;
  98.     texDesc.Layout = D3D12_TEXTURE_LAYOUT_UNKNOWN;
  99.     texDesc.Flags = D3D12_RESOURCE_FLAG_ALLOW_UNORDERED_ACCESS;
  100.  
  101.     ThrowIfFailed(md3dDevice->CreateCommittedResource(
  102.         &CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_DEFAULT),
  103.         D3D12_HEAP_FLAG_NONE,
  104.         &texDesc,
  105.         D3D12_RESOURCE_STATE_COMMON,
  106.         nullptr,
  107.         IID_PPV_ARGS(&mPrevSol)));
  108.  
  109.     ThrowIfFailed(md3dDevice->CreateCommittedResource(
  110.         &CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_DEFAULT),
  111.         D3D12_HEAP_FLAG_NONE,
  112.         &texDesc,
  113.         D3D12_RESOURCE_STATE_COMMON,
  114.         nullptr,
  115.         IID_PPV_ARGS(&mCurrSol)));
  116.  
  117.     ThrowIfFailed(md3dDevice->CreateCommittedResource(
  118.         &CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_DEFAULT),
  119.         D3D12_HEAP_FLAG_NONE,
  120.         &texDesc,
  121.         D3D12_RESOURCE_STATE_COMMON,
  122.         nullptr,
  123.         IID_PPV_ARGS(&mNextSol)));
  124.  
  125.     //
  126.     // In order to copy CPU memory data into our default buffer, we need to create
  127.     // an intermediate upload heap. 
  128.     //
  129.  
  130.     const UINT num2DSubresources = texDesc.DepthOrArraySize * texDesc.MipLevels;
  131.     const UINT64 uploadBufferSize = GetRequiredIntermediateSize(mCurrSol.Get(), 0, num2DSubresources);
  132.  
  133.     ThrowIfFailed(md3dDevice->CreateCommittedResource(
  134.         &CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_UPLOAD),
  135.         D3D12_HEAP_FLAG_NONE,
  136.         &CD3DX12_RESOURCE_DESC::Buffer(uploadBufferSize),
  137.         D3D12_RESOURCE_STATE_GENERIC_READ,
  138.         nullptr,
  139.         IID_PPV_ARGS(mPrevUploadBuffer.GetAddressOf())));
  140.  
  141.     ThrowIfFailed(md3dDevice->CreateCommittedResource(
  142.         &CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_UPLOAD),
  143.         D3D12_HEAP_FLAG_NONE,
  144.         &CD3DX12_RESOURCE_DESC::Buffer(uploadBufferSize),
  145.         D3D12_RESOURCE_STATE_GENERIC_READ,
  146.         nullptr,
  147.         IID_PPV_ARGS(mCurrUploadBuffer.GetAddressOf())));
  148.  
  149.     // Describe the data we want to copy into the default buffer.
  150.     std::vector<float> initData(mNumRows*mNumCols, 0.0f);
  151.     for(int i = 0; i < initData.size(); ++i)
  152.         initData[i] = 0.0f;
  153.  
  154.     D3D12_SUBRESOURCE_DATA subResourceData = {};
  155.     subResourceData.pData = initData.data();
  156.     subResourceData.RowPitch = mNumCols*sizeof(float);
  157.     subResourceData.SlicePitch = subResourceData.RowPitch * mNumRows;
  158.  
  159.     //
  160.     // Schedule to copy the data to the default resource, and change states.
  161.     // Note that mCurrSol is put in the GENERIC_READ state so it can be 
  162.     // read by a shader.
  163.     //
  164.  
  165.     cmdList->ResourceBarrier(1, &CD3DX12_RESOURCE_BARRIER::Transition(mPrevSol.Get(),
  166.         D3D12_RESOURCE_STATE_COMMON, D3D12_RESOURCE_STATE_COPY_DEST));
  167.     UpdateSubresources(cmdList, mPrevSol.Get(), mPrevUploadBuffer.Get(), 0, 0, num2DSubresources, &subResourceData);
  168.     cmdList->ResourceBarrier(1, &CD3DX12_RESOURCE_BARRIER::Transition(mPrevSol.Get(),
  169.         D3D12_RESOURCE_STATE_COPY_DEST, D3D12_RESOURCE_STATE_UNORDERED_ACCESS));
  170.  
  171.     cmdList->ResourceBarrier(1, &CD3DX12_RESOURCE_BARRIER::Transition(mCurrSol.Get(),
  172.         D3D12_RESOURCE_STATE_COMMON, D3D12_RESOURCE_STATE_COPY_DEST));
  173.     UpdateSubresources(cmdList, mCurrSol.Get(), mCurrUploadBuffer.Get(), 0, 0, num2DSubresources, &subResourceData);
  174.     cmdList->ResourceBarrier(1, &CD3DX12_RESOURCE_BARRIER::Transition(mCurrSol.Get(),
  175.         D3D12_RESOURCE_STATE_COPY_DEST, D3D12_RESOURCE_STATE_GENERIC_READ));
  176.  
  177.     cmdList->ResourceBarrier(1, &CD3DX12_RESOURCE_BARRIER::Transition(mNextSol.Get(),
  178.         D3D12_RESOURCE_STATE_COMMON, D3D12_RESOURCE_STATE_UNORDERED_ACCESS));
  179. }
  180.  
  181. void GpuWaves::BuildDescriptors(
  182.     CD3DX12_CPU_DESCRIPTOR_HANDLE hCpuDescriptor,
  183.     CD3DX12_GPU_DESCRIPTOR_HANDLE hGpuDescriptor,
  184.     UINT descriptorSize)
  185. {
  186.     D3D12_SHADER_RESOURCE_VIEW_DESC srvDesc = {};
  187.     srvDesc.Shader4ComponentMapping = D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING;
  188.     srvDesc.Format = DXGI_FORMAT_R32_FLOAT;
  189.     srvDesc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE2D;
  190.     srvDesc.Texture2D.MostDetailedMip = 0;
  191.     srvDesc.Texture2D.MipLevels = 1;
  192.     
  193.     D3D12_UNORDERED_ACCESS_VIEW_DESC uavDesc = {};
  194.  
  195.     uavDesc.Format = DXGI_FORMAT_R32_FLOAT;
  196.     uavDesc.ViewDimension = D3D12_UAV_DIMENSION_TEXTURE2D;
  197.     uavDesc.Texture2D.MipSlice = 0;
  198.  
  199.     md3dDevice->CreateShaderResourceView(mPrevSol.Get(), &srvDesc, hCpuDescriptor);
  200.     md3dDevice->CreateShaderResourceView(mCurrSol.Get(), &srvDesc, hCpuDescriptor.Offset(1, descriptorSize));
  201.     md3dDevice->CreateShaderResourceView(mNextSol.Get(), &srvDesc, hCpuDescriptor.Offset(1, descriptorSize));
  202.  
  203.     md3dDevice->CreateUnorderedAccessView(mPrevSol.Get(), nullptr, &uavDesc, hCpuDescriptor.Offset(1, descriptorSize));
  204.     md3dDevice->CreateUnorderedAccessView(mCurrSol.Get(), nullptr, &uavDesc, hCpuDescriptor.Offset(1, descriptorSize));
  205.     md3dDevice->CreateUnorderedAccessView(mNextSol.Get(), nullptr, &uavDesc, hCpuDescriptor.Offset(1, descriptorSize));
  206.  
  207.     // Save references to the GPU descriptors. 
  208.     mPrevSolSrv = hGpuDescriptor;
  209.     mCurrSolSrv = hGpuDescriptor.Offset(1, descriptorSize);
  210.     mNextSolSrv = hGpuDescriptor.Offset(1, descriptorSize);
  211.     mPrevSolUav = hGpuDescriptor.Offset(1, descriptorSize);
  212.     mCurrSolUav = hGpuDescriptor.Offset(1, descriptorSize);
  213.     mNextSolUav = hGpuDescriptor.Offset(1, descriptorSize);
  214. }
  215.  
  216. void GpuWaves::Update(
  217.     const GameTimer& gt,
  218.     ID3D12GraphicsCommandList* cmdList,
  219.     ID3D12RootSignature* rootSig,
  220.     ID3D12PipelineState* pso)
  221. {
  222.     static float t = 0.0f;
  223.  
  224.     // Accumulate time.
  225.     t += gt.DeltaTime();
  226.  
  227.     cmdList->SetPipelineState(pso);
  228.     cmdList->SetComputeRootSignature(rootSig);
  229.  
  230.     // Only update the simulation at the specified time step.
  231.     if(t >= mTimeStep)
  232.     {
  233.         // Set the update constants.
  234.         cmdList->SetComputeRoot32BitConstants(0, 3, mK, 0);
  235.  
  236.         cmdList->SetComputeRootDescriptorTable(1, mPrevSolUav);
  237.         cmdList->SetComputeRootDescriptorTable(2, mCurrSolUav);
  238.         cmdList->SetComputeRootDescriptorTable(3, mNextSolUav);
  239.  
  240.         // How many groups do we need to dispatch to cover the wave grid.  
  241.         // Note that mNumRows and mNumCols should be divisible by 16
  242.         // so there is no remainder.
  243.         UINT numGroupsX = mNumCols / 16;
  244.         UINT numGroupsY = mNumRows / 16;
  245.         cmdList->Dispatch(numGroupsX, numGroupsY, 1);
  246.  
  247.         //
  248.         // Ping-pong buffers in preparation for the next update.
  249.         // The previous solution is no longer needed and becomes the target of the next solution in the next update.
  250.         // The current solution becomes the previous solution.
  251.         // The next solution becomes the current solution.
  252.         //
  253.  
  254.         auto resTemp = mPrevSol;
  255.         mPrevSol = mCurrSol;
  256.         mCurrSol = mNextSol;
  257.         mNextSol = resTemp;
  258.  
  259.         auto srvTemp = mPrevSolSrv;
  260.         mPrevSolSrv = mCurrSolSrv;
  261.         mCurrSolSrv = mNextSolSrv;
  262.         mNextSolSrv = srvTemp;
  263.  
  264.         auto uavTemp = mPrevSolUav;
  265.         mPrevSolUav = mCurrSolUav;
  266.         mCurrSolUav = mNextSolUav;
  267.         mNextSolUav = uavTemp;
  268.  
  269.         t = 0.0f; // reset time
  270.  
  271.         // The current solution needs to be able to be read by the vertex shader, so change its state to GENERIC_READ.
  272.         cmdList->ResourceBarrier(1, &CD3DX12_RESOURCE_BARRIER::Transition(mCurrSol.Get(),
  273.             D3D12_RESOURCE_STATE_UNORDERED_ACCESS, D3D12_RESOURCE_STATE_GENERIC_READ));
  274.     }
  275. }
  276.  
  277. void GpuWaves::Disturb(
  278.     ID3D12GraphicsCommandList* cmdList,
  279.     ID3D12RootSignature* rootSig,
  280.     ID3D12PipelineState* pso,
  281.     UINT i, UINT j,
  282.     float magnitude)
  283. {
  284.     cmdList->SetPipelineState(pso);
  285.     cmdList->SetComputeRootSignature(rootSig);
  286.  
  287.     // Set the disturb constants.
  288.     UINT disturbIndex[2] = { j, i };
  289.     cmdList->SetComputeRoot32BitConstants(0, 1, &magnitude, 3);
  290.     cmdList->SetComputeRoot32BitConstants(0, 2, disturbIndex, 4);
  291.  
  292.     cmdList->SetComputeRootDescriptorTable(3, mCurrSolUav);
  293.  
  294.     // The current solution is in the GENERIC_READ state so it can be read by the vertex shader.
  295.     // Change it to UNORDERED_ACCESS for the compute shader.  Note that a UAV can still be
  296.     // read in a compute shader.
  297.     cmdList->ResourceBarrier(1, &CD3DX12_RESOURCE_BARRIER::Transition(mCurrSol.Get(),
  298.         D3D12_RESOURCE_STATE_GENERIC_READ, D3D12_RESOURCE_STATE_UNORDERED_ACCESS));
  299.  
  300.     // One thread group kicks off one thread, which displaces the height of one
  301.     // vertex and its neighbors.
  302.     cmdList->Dispatch(1, 1, 1);
  303. }
  304.  
  305.  
  306.  
  307.